using System;
using System.Text;
using System.Reflection;
using System.Collections.Generic;

using Open.Data.Persistence.Definitions;

namespace Open.Data.Persistence
{
    //Events signatures for verifying and deploying assemblies, types and properties
    public delegate void DeployAssemblyHandler(object sender, DeployAssemblyEventArgs e);

    public delegate void PreValidateEventHandler(object sender, PreValidateEventArgs e);
    public delegate void PostValidateEventHandler(object sender, PostValidateEventArgs e);
    
    public delegate void PreValidateKeyEventHandler(object sender, PreValidateKeyEventArgs e);
    public delegate void PostValidateKeyEventHandler(object sender, PostValidateKeyEventArgs e);

    public delegate void PreValidateReferenceEventHandler(object sender, PreValidateReferenceEventArgs e);
    public delegate void PostValidateReferenceEventHandler(object sender, PostValidateReferenceEventArgs e);

    public delegate void PreValidateIndexEventHandler(object sender, PreValidateIndexEventArgs e);
    public delegate void PostValidateIndexEventHandler(object sender, PostValidateIndexEventArgs e);

    public delegate void PreDeployTypeHandler(object sender, PreDeployTypeEventArgs e);
    public delegate void PostDeployTypeHandler(object sender, PostDeployTypeEventArgs e);
    public delegate void DeployTypeExceptionHandler(object sender, DeployTypeExceptionEventArgs e);

    public delegate void AddTableEventHandler(object sender, AddTableEventInfo e);
    public delegate void ChangeTableEventHandler(object sender, ChangeTableEventInfo e);

    public delegate void ExecuteScriptEventHandler(object sender, ExecuteScriptEventArgs e);

    public class DeployAssemblyEventArgs
    {
        private Assembly _assembly;
        private DeploymentMode _deploymentMode;
        private DeploymentType _deploymentType;
        private bool _cancel;

        public DeployAssemblyEventArgs(Assembly assembly, DeploymentMode deploymentMode, DeploymentType deploymentType)
        {
            _assembly = assembly;
            _deploymentMode = deploymentMode;
            _deploymentType = deploymentType;
            _cancel = false;
        }

        public Assembly Assembly
        {
            get
            {
                return _assembly;
            }
        }

        public DeploymentMode DeploymentMode
        {
            get
            {
                return _deploymentMode;
            }
        }

        public DeploymentType DeploymentType
        {
            get
            {
                return _deploymentType;
            }
        }

        public bool Cancel
        {
            get
            {
                return _cancel;
            }
            set
            {
                _cancel = value;
            }
        }
    }

    public abstract class ValidateTypeEventArgs
    {
        public ValidateTypeEventArgs(Type type)
        {
            Type = type;
        }

        public Type Type {get; set;}
    }

    public class PreValidateEventArgs: ValidateTypeEventArgs
    {
        public PreValidateEventArgs(Type type): base(type)
        {
        }
        public bool Cancel {get; set;}
    }

    public class PostValidateEventArgs : ValidateTypeEventArgs
    {
        public PostValidateEventArgs(Type type): base(type)
        {
        }
        public bool Changed { get; set; }
        public bool Exists { get; set; }
        public string Script { get; set; }
    }

    public class PreValidateKeyEventArgs : PreValidateEventArgs
    {
        private KeyDefinition _keyDefinition;

        public PreValidateKeyEventArgs(Type type): base(type)
        {
        }

        public PreValidateKeyEventArgs(Type type, KeyDefinition keyDefinition): base(type)
        {
            _keyDefinition = keyDefinition;
        }

        public KeyDefinition KeyDefinition
        {
            get
            {
                return _keyDefinition;
            }
        }
    }

    public class PostValidateKeyEventArgs : PostValidateEventArgs
    {
        public PostValidateKeyEventArgs(Type type): base(type)
        {
        }
    }

    public class PreValidateReferenceEventArgs : PreValidateEventArgs
    {
        private Type _referenceType;

        public PreValidateReferenceEventArgs(Type type): base(type)
        {
        }

        public PreValidateReferenceEventArgs(Type type, Type referenceType): base(type)
        {
            _referenceType = referenceType;
        }

        public Type ReferenceType
        {
            get
            {
                return _referenceType;
            }
        }
    }

    public class PostValidateReferenceEventArgs: PostValidateEventArgs
    {
        private Type _referenceType;

        public PostValidateReferenceEventArgs(Type type): base(type)
        {
        }

        public PostValidateReferenceEventArgs(Type type, Type referenceType): base(type)
        {
            _referenceType = referenceType;
        }

        public Type ReferenceType
        {
            get
            {
                return _referenceType;
            }
        }
    }

    public class PreValidateIndexEventArgs : PreValidateEventArgs
    {
        public PreValidateIndexEventArgs(Type type): base(type)
        {
        }
    }

    public class PostValidateIndexEventArgs : PostValidateEventArgs
    {
        public PostValidateIndexEventArgs(Type type): base(type)
        {
        }
    }

    public abstract class DeployTypeEventArgs
    {
        //Property variables
        private Type _type;
        private string _name;

        public DeployTypeEventArgs(Type type, string name)
        {
            _type = type;
            _name = name;
        }

        public Type Type
        {
            get
            {
                return _type;
            }
        }

        public string Name
        {
            get
            {
                return _name;
            }
        }
    }

    public class PreDeployTypeEventArgs: DeployTypeEventArgs
    {
        public PreDeployTypeEventArgs(Type type, string name): base(type, name)
        {
            Cancel = false;
        }

        public bool Cancel {get; set;}
    }

    public class PostDeployTypeEventArgs: DeployTypeEventArgs
    {
        //Property variables
        private string _script;

        public PostDeployTypeEventArgs(Type type, string name, string script): base(type, name)
        {
            _script = script;
        }

        public string Script
        {
            get
            {
                return _script;
            }
        }
    }

    public class DeployTypeExceptionEventArgs : DeployTypeEventArgs
    {
        public DeployTypeExceptionEventArgs(Type type, string name, string script, Exception e): base(type, name)
        {
            Script = script;
            Exception = e;
        }

        public string Script {get; set;}
        public Exception Exception {get; set;}
    }

    public class ExecuteScriptEventArgs
    {        
        public ExecuteScriptEventArgs(string script)
        {
            Script = script;
        }

        public string Script {get; set;}
    }

    public class TableEventInfo
    {
        //Property variables
        private Type _type;
        private string _name;

        public TableEventInfo(Type type, string name)
        {
            _type = type;
            _name = name;
        }

        public Type Type
        {
            get
            {
                return _type;
            }
        }

        public string Name
        {
            get
            {
                return _name;
            }
        }
    }

    public class AddTableEventInfo: TableEventInfo
    {
        TableDefinition _definition;

        public AddTableEventInfo(Type type, string name, TableDefinition definition): base(type, name)
        {
            _definition = definition;
        }

        public TableDefinition TableDefinition
        {
            get
            {
                return _definition;
            }
        }
    }

    public class ChangeTableEventInfo: TableEventInfo
    {
        TableDefinition _definition;
        KeyDefinition _keyDefinition;
        TableModification _modification;

        public ChangeTableEventInfo(Type type, string name, TableDefinition definition, KeyDefinition keyDefinition, TableModification modification): base(type, name)
        {
            _definition = definition;
            _keyDefinition = keyDefinition;
            _modification = modification;
        }

        public TableDefinition TableDefinition
        {
            get
            {
                return _definition;
            }
        }

        public TableModification TableModification
        {
            get
            {
                return _modification;
            }
        }

        public KeyDefinition KeyDefinition
        {
            get
            {

                return _keyDefinition;
            }
        }
    }

    public class ColumnEventInfo: TableEventInfo
    {
        PropertyInfo _propertyInfo;
        string _columnName;

        public ColumnEventInfo(Type type, string name, PropertyInfo property, string columnName): base(type, name)
        {
            _propertyInfo = property;
            _columnName = columnName;
        }

        public PropertyInfo Property
        {
            get
            {
                return _propertyInfo;
            }
        }

        public string ColumnName
        {
            get
            {
                return _columnName;
            }
        }
    }
}
